﻿using System.Collections.Generic;
using CF.CFLog;
using CF.Core;
using UnityEngine;

namespace CF.Pool
{
    public class PoolList
    {
        /// <summary>
        /// 生成的物体
        /// </summary>
        protected HashSet<GameObject> SpawnObjects;

        /// <summary>
        /// 被回收的物体
        /// </summary>
        protected HashSet<GameObject> DespawnObjects;

        /// <summary>
        /// 已被回收物体个数
        /// </summary>
        public int DespawnObjectCount => DespawnObjects.Count;

        private PoolConfig poolConfig;

        public PoolList(PoolConfig _poolConfig)
        {
            poolConfig = _poolConfig;
            SpawnObjects = new HashSet<GameObject>();
            DespawnObjects = new HashSet<GameObject>();
        }

        public GameObject Spawn(GameObject prefab, Transform parent)
        {
            return Spawn(prefab, Vector3.zero, Quaternion.identity, parent);
        }

        public GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion quaternion, Transform parent)
        {
            GameObject instanceGo = null;
            foreach (var go in DespawnObjects)
            {
                instanceGo = go;
                break;
            }

            if (instanceGo != null)
            {
                DespawnObjects.Remove(instanceGo);
                SpawnObjects.Add(instanceGo);
                SetProperty(instanceGo, pos, quaternion, parent);
                instanceGo.SetActive(true);
                return instanceGo;
            }

            instanceGo = InstanceObjct(prefab);
            SpawnObjects.Add(instanceGo);
            SetProperty(instanceGo, pos, quaternion, parent);
            return instanceGo;
        }

        public void Despawn(GameObject instanceGo)
        {
            if (!SpawnObjects.Contains(instanceGo))
            {
               Log.Error($"{instanceGo.name} Is not in spawnList. It will be destroyed.");
                Object.Destroy(instanceGo);
                return;
            }

            SpawnObjects.Remove(instanceGo);

            if (DespawnObjectCount > poolConfig.MaxObjectCount)
            {
                Log.Info($"Pool Is full. {instanceGo.name} will be destroyed.");
                Object.Destroy(instanceGo);
            }
            else
            {
                instanceGo.SetActive(false);
                DespawnObjects.Add(instanceGo);
            }
        }

        public void ClearDespawnPool()
        {
            // foreach (var go in SpawnObjects) {
            // 	Object.Destroy (go);
            // }
            //
            // SpawnObjects.Clear ();
            foreach (var go in DespawnObjects)
            {
                Object.Destroy(go);
            }

            DespawnObjects.Clear();
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public void Destroy()
        {
            foreach (var go in SpawnObjects)
            {
                Object.Destroy(go);
            }

            SpawnObjects.Clear();
            foreach (var go in DespawnObjects)
            {
                Object.Destroy(go);
            }

            DespawnObjects.Clear();
            SpawnObjects = null;
            DespawnObjects = null;
        }

        /// <summary>
        /// 实例化物体
        /// </summary>
        /// <param name="prefab"></param>
        /// <returns></returns>
        private GameObject InstanceObjct(GameObject prefab)
        {
            return Object.Instantiate(prefab);
        }

        /// <summary>
        /// 设置生成的物体的属性
        /// </summary>
        /// <param name="go"></param>
        /// <param name="pos"></param>
        /// <param name="quaternion"></param>
        /// <param name="parent"></param>
        private void SetProperty(GameObject go, Vector3 pos, Quaternion quaternion, Transform parent)
        {
            go.transform.position = pos;
            go.transform.rotation = quaternion;
            if (parent != null && go.transform.parent != parent)
            {
                go.transform.SetParent(parent);
            }
        }
    }
}